package cn.tedu.charging.cost.service;

import cn.tedu.charging.common.pojo.param.ProgressCostParam;
import cn.tedu.charging.common.pojo.po.ChargingCostRulePO;
import cn.tedu.charging.common.pojo.vo.ProgressCostVO;
import cn.tedu.charging.cost.repo.CostRepo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;

@Service
public class CostServiceImpl implements CostService {
    @Autowired
    private CostRepo costRepo;
    /**
     * redisTemplate底层序列化模式 RedisSerializer.java()
     * 导致在redis存储的string数据 不是数字 123->\X0\X1\X9123
     * 需要替换成RedisSerializer.string();
     */
    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public ProgressCostVO calculateBill(ProgressCostParam param) {
        /**
         * 关于充电计价，根据时间接机点，根据充电站设备类型等不同条件因素，读取的规定结果
         */
        // 1. 拿到充电单价，到charging-cost-rule中读取计价规则
        // select * from charging_cost_rule where 站场Id 枪类型 时间段
        // 站场Id=param.getStationId 枪类型=远程调用的详细数据.getType()
        /**
         * 尖（上午/下午）：8-12 14-18
         * 峰：18-24
         * 平：12-14
         * 谷：0-8
         * start_time<=now()<end_time --> [0,8) [8,12) [12,14) [14,18) [18,24)
         */
        ChargingCostRulePO costRule = getCostRule(param.getStationId(), new Date());  // 拿到满足条件的计价规则
        // 2. 查询价格规则，可以根据参数充电度数 做结算 单次金额 powFee*param.getChargingCapacity()
        BigDecimal perFee = calculatePowerfee(param.getChargingCapacity(), costRule.getPowerFee());
        // 3. 计算历史叠加累计金额
        BigDecimal totalFee = accumlatePowerfee(perFee, param.getOrderNo());
        // 封装vo返回
        ProgressCostVO vo = new ProgressCostVO();
        vo.setPowerFee(costRule.getPowerFee().doubleValue());
        vo.setTotalCost(totalFee.doubleValue());
        return vo;
    }

    private BigDecimal accumlatePowerfee(BigDecimal perFee, String orderNo) {
        // 单次计价为5元，累计金额，需要历史累计金额 上次计算的总价
        // redis计步器
        // 1. 准备每张订单 累计金额的key
        String orderCostTotalKey = "order:cost:total:" + orderNo;
        // 2. 将单次金额perFee转化成int，累加，redis客户端已经实现该转化
        // incrby key perFee
        Double increment = redisTemplate.boundValueOps(orderCostTotalKey).increment(perFee.doubleValue());
        return new BigDecimal(increment);
    }

    private BigDecimal calculatePowerfee(Double chargingCapacity, BigDecimal powerFee) {
        // 乘法执行 api代码 精度2位，四舍五入
        // 所有计算单价的数据都转化为大数
        BigDecimal perFee = new BigDecimal(chargingCapacity).multiply(powerFee);
        if (perFee.compareTo(BigDecimal.ZERO) > 0) {  // 虽然大概率不可能为0或负数，但还是判断一下
            return perFee.setScale(2, BigDecimal.ROUND_HALF_UP);
        }
        return BigDecimal.ZERO;  // 为0或负数直接返回0
    }

    private ChargingCostRulePO getCostRule(Integer stationId, Date date) {
        return costRepo.getCostRule(stationId, date);
    }
}
